package is.server.model.xtool;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.Arrays;

/**
 * @author aspr0
 *         Date: 27.05.12
 *         Time: 0:15
 */
public class ConcatDupless
{
    private Document dbDoc;
    NodeList sections;
    NodeList sectionsAlien;

    public ConcatDupless(Document dbDoc, Document dbDocAlien)
    {
        this.dbDoc = dbDoc;
        sections = dbDoc.getChildNodes().item(0).getChildNodes();
        sectionsAlien = dbDocAlien.getChildNodes().item(0).getChildNodes();
    }

    /**
     * Starts concatenation process
     *
     * @return count of removed duplicates
     */
    public int process()
    {
        int removedDupsCount = removeDuplicates();
        reinitIds();
        concat();

        return removedDupsCount;
    }


    /**
     * Removes entries from dbDocAlien which duplicate existing ones in dbDoc
     *
     * @return duplicatesRemovedCount
     */
    private int removeDuplicates()
    {
        int duplicatesRemovedCount = 0;

        for (int sectionNum = 0; sectionNum < 2; sectionNum++)
        {
            Node sectionAlien = sectionsAlien.item(sectionNum);

            NodeList rows = sections.item(sectionNum).getChildNodes();
            NodeList rowsAlien = sectionsAlien.item(sectionNum).getChildNodes();
            int rowCount = rows.getLength();


            for (int rowNumAlien = 0; rowNumAlien < rowsAlien.getLength(); )
            {
                /* selecting one alien row */
                Node rowAlien = rowsAlien.item(rowNumAlien);

                NodeList entriesAlien = rowsAlien.item(rowNumAlien).getChildNodes();

                String[] employeeNameAlien = null;
                String departmentNameAlien = null;

                /* preparing unique entries from this row to compare */
                switch (sectionNum)
                {
                    case 0:
                        employeeNameAlien = new String[]{entriesAlien.item(1).getTextContent(),
                                entriesAlien.item(2).getTextContent(), entriesAlien.item(3).getTextContent()};
                        break;

                    case 1:
                        departmentNameAlien = entriesAlien.item(1).getTextContent();
                        break;

                }

                boolean removeOccurred = false;

                /* comparing entries that should be unique from alien row with existing ones */
                for (int rowNum = 0; rowNum < rowCount; rowNum++)
                {
                    NodeList entries = rows.item(rowNum).getChildNodes();

                    switch (sectionNum)
                    {
                        case 0:
                            String[] employeeName = new String[]{entries.item(1).getTextContent(),
                                    entries.item(2).getTextContent(), entries.item(3).getTextContent()};


                            if (Arrays.equals(employeeName, employeeNameAlien))
                            {
                                sectionAlien.removeChild(rowAlien);

                                duplicatesRemovedCount++;
                                removeOccurred = true;
                                break;
                            }


                            break;

                        case 1:
                            String departmentName = entries.item(1).getTextContent();

                            if (departmentName.equals(departmentNameAlien))
                            {
                                sectionAlien.removeChild(rowAlien);

                                duplicatesRemovedCount++;
                                removeOccurred = true;
                                break;
                            }
                            break;
                    }
                }

                if (!removeOccurred)
                {
                    /* if remove occurred next row will become current otherwise we go next row */
                    rowNumAlien++;
                }
            }
        }
        return duplicatesRemovedCount;
    }

    private void reinitIds()
    {
        for (int sectionNum = 0; sectionNum < 2; sectionNum++)
        {
            Integer id = 0;

            if (sections.item(sectionNum).getChildNodes().getLength() > 0)
            {
                Node lastRow = sections.item(sectionNum).getLastChild();
                String idString = lastRow.getChildNodes().item(0).getTextContent();
                id = Integer.parseInt(idString);
            }

            id++;


            NodeList rowsAlien = sectionsAlien.item(sectionNum).getChildNodes();

            int rowAlienCount = rowsAlien.getLength();
            for (int rowAlienNum = 0; rowAlienNum < rowAlienCount; rowAlienNum++)
            {
                Node idNode = rowsAlien.item(rowAlienNum).getChildNodes().item(0);

                idNode.setTextContent(id.toString());

                if (sectionNum == 2)
                {
                    String depIdToSearch = idNode.getTextContent();
                    replaceDepId(depIdToSearch, id.toString());
                }

                id++;
            }
        }
    }

    private void replaceDepId(String depIdToSearch, String depIdToPlace)
    {
        NodeList employeeSectionsAlien = sectionsAlien.item(0).getChildNodes();
        int esaRowCount = employeeSectionsAlien.getLength();

        for (int rowNum = 0; rowNum < esaRowCount; rowNum++)
        {
            Node depIdCurrentNode = employeeSectionsAlien.item(rowNum).getChildNodes().item(4);
            String depIdCurrent = depIdCurrentNode.getTextContent();

            if (depIdCurrent.equals(depIdToSearch))
            {
                depIdCurrentNode.setTextContent(depIdToPlace);
            }
        }
    }

    private void concat()
    {
        for (int sectionNum = 0; sectionNum < 2; sectionNum++)
        {
            Node section = sections.item(sectionNum);
            Node sectionAlien = sectionsAlien.item(sectionNum);

            NodeList rowsAlien = sectionAlien.getChildNodes();
            int rowCountAlien = rowsAlien.getLength();

            for (int rowNumAlien = 0; rowNumAlien < rowCountAlien; rowNumAlien++)
            {
                Node rowAlien = rowsAlien.item(rowNumAlien);

                rowAlien = dbDoc.importNode(rowAlien, true);
                section.appendChild(rowAlien);
            }
        }
    }
}
